import Mat4 from "./Mat4";
import Trs from "./Trs";
import Vec3 from "./Vec3";
import Quaternion from "./Quaternion";
import BoundingSphere from "./BoundingSphere";

export default class Model {
    name: string = "NewModel"
    position: Vec3 = null;
    rotation: Quaternion = null;
    scale: Vec3 = null;
    boundingSphere: BoundingSphere = null; // 添加包围球属性
    buffers = null;
    program: WebGLProgram = null;
    modelMatrix: Mat4 = null;
    loaded = false;
    constructor(name) {
        this.name = name;
        this.position = new Vec3(0, 0, 0);
        this.rotation = new Quaternion();
        this.scale = new Vec3(1, 1, 1);
        this.modelMatrix = new Mat4();
        this.updateBoundingSphere();
    }
    setScale(xOrScale, y, z) {
        // TODO: 实现设置模型缩放
        if (xOrScale instanceof Vec3) {
            this.scale = xOrScale;
        }
        else {
            this.scale.x = xOrScale;
            this.scale.y = y;
            this.scale.z = z;
        }
        this.updateBoundingSphere();
    }
    setPosition(xOrPos, y, z) {
        // TODO: 实现设置模型位置
        if (xOrPos instanceof Vec3) {
            this.position = xOrPos;
        } else {
            this.position.x = xOrPos;
            this.position.y = y;
            this.position.z = z;
        }
        this.updateBoundingSphere();
    }
    setProgram(program: WebGLProgram) {
        this.program = program;
    }
    static parseObj(content) {
        const lines = content.split("\n");
        const vertices = [];
        const normals = [];
        const textureCoords = [];
        const faces = [];

        lines.forEach((line) => {
            const values = line.split(" ");
            const type = values[0];

            switch (type) {
                case "v": // 顶点
                    vertices.push(
                        parseFloat(values[1]),
                        parseFloat(values[2]),
                        parseFloat(values[3])
                    );
                    break;

                case "vt": // 纹理坐标
                    textureCoords.push(
                        parseFloat(values[1]),
                        parseFloat(values[2])
                    );
                    break;

                case "vn": // 法线
                    normals.push([
                        parseFloat(values[1]),
                        parseFloat(values[2]),
                        parseFloat(values[3])
                    ]);
                    break;

                case "f": // 面
                    const face = values.slice(1).map((vertex) => {
                        const indices = vertex
                            .split("/")
                            .map((index) => parseInt(index));
                        return indices;
                    });
                    faces.push(face);
                    break;

                default:
                    break;
            }
        });

        // console.log('Vertices:', vertices);
        // console.log('Normals:', normals);
        // console.log('Texture Coords:', textureCoords);
        // console.log('Faces:', faces);

        return { vertices, normals, textureCoords, faces };
    }
    insertOnes(arr) {
        // 检查数组长度是否是3的倍数
        if (arr.length % 3 !== 0) {
            throw new Error("数组长度必须是3的倍数");
        }

        // 创建一个新数组来存储结果
        let result = [];

        // 遍历原始数组
        for (let i = 0; i < arr.length; i++) {
            // 将当前元素添加到结果数组中
            result.push(arr[i]);

            // 每三个元素后插入四个1
            if ((i + 1) % 3 === 0) {
                result.push(0.6, 0.6, 0.6, 1);
            }
        }

        return result;
    }
    calculateVertexNormals(vertices, indices) {
        const vertexNormals = new Array(vertices.length / 3).fill(0).map(() => [0, 0, 0]);

        // 遍历所有三角形
        for (let i = 0; i < indices.length; i += 3) {
            const v1 = vertices.slice(indices[i] * 3, indices[i] * 3 + 3);
            const v2 = vertices.slice(indices[i + 1] * 3, indices[i + 1] * 3 + 3);
            const v3 = vertices.slice(indices[i + 2] * 3, indices[i + 2] * 3 + 3);

            // 计算边向量
            const edge1 = [v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]];
            const edge2 = [v3[0] - v1[0], v3[1] - v1[1], v3[2] - v1[2]];

            // 计算面法线
            const faceNormal = [
                edge1[1] * edge2[2] - edge1[2] * edge2[1],
                edge1[2] * edge2[0] - edge1[0] * edge2[2],
                edge1[0] * edge2[1] - edge1[1] * edge2[0]
            ];

            // 将面法线累加到每个顶点的法线
            for (let j = 0; j < 3; j++) {
                const index = indices[i + j];
                vertexNormals[index][0] += faceNormal[0];
                vertexNormals[index][1] += faceNormal[1];
                vertexNormals[index][2] += faceNormal[2];
            }
        }

        // 归一化顶点法线
        for (let i = 0; i < vertexNormals.length; i++) {
            const normal = vertexNormals[i];
            const length = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
            vertexNormals[i] = [normal[0] / length, normal[1] / length, normal[2] / length];
        }

        return vertexNormals;
    }
    async loadBuffers(gl, url) {

        let response = await fetch(url);
        let text = await response.text()
        // console.log("response", text);
        let obj = Model.parseObj(text);
        let vertices = obj.vertices;
        let indices = [];
        let normals = [] // 初始化法线数组

        for (let i = 0; i < obj.faces.length; i++) {
            const face = obj.faces[i];
            let normal = obj.normals[i]
            for (let offset = 0; offset < face.length - 2; offset++) {
                // let vertexIndex = face[offset][0] - 1; // 顶点索引
                // let normalIndex = face[offset][2] - 1; // 法线索引
                indices.push(
                    face[0][0] - 1,
                    face[1 + offset][0] - 1,
                    face[2 + offset][0] - 1
                );
            }
        }
        // console.log(vertices.length)
        // 计算法线
        let normalsarr = this.calculateVertexNormals(vertices, indices);
        for (let i = 0; i < normalsarr.length; i++) {
            normals.push(...normalsarr[i]);
        }
        vertices = this.insertOnes(vertices);
        // console.log('vertices', vertices);
        console.log('normals', normals)
        this.buffers = this.createBuffers(gl, vertices, normals, indices);
        this.loaded = true;
    }
    updateBoundingSphere() {
        // 假设模型的半径为最大顶点到中心的距离
        const maxDistance = Math.max(this.scale.x, this.scale.y, this.scale.z);
        this.boundingSphere = new BoundingSphere(this.position, maxDistance);
    }
    createBuffers(gl, vertices, normals, indices) {
        const vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

        const normalBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);

        const indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

        return { vertexBuffer, normalBuffer, indexBuffer, indexCount: indices.length };
    }
    updateModelMatrix() {
        let trs = [
            this.position.x,
            this.position.y,
            this.position.z,
            this.rotation.x,
            this.rotation.y,
            this.rotation.z,
            this.rotation.w,
            this.scale.x,
            this.scale.y,
            this.scale.z

        ]
        Trs.toMat4(this.modelMatrix, trs);
    }

    // 实现 lookAt 函数
    lookAt(target: Vec3, up: Vec3 = new Vec3(0, 1, 0)): Quaternion {
        let eye = this.position;
        // 计算方向向量
        const forward = Vec3.subtract(target, eye).normalize();
        const right = Vec3.cross(up, forward).normalize();
        const upDir = Vec3.cross(forward, right);

        // 计算旋转轴和角度
        const axis = Vec3.cross(new Vec3(0, 1, 0), forward);
        const angle = Math.acos(Vec3.dot(new Vec3(0, 0, 1), forward));

        // 构造四元数
        const forwardQuat = Quaternion.fromAxisAngle(axis, angle);

        // 计算围绕y轴的旋转
        const yAxis = Vec3.cross(new Vec3(0, 1, 0), upDir);
        const yAngle = Math.acos(Vec3.dot(new Vec3(0, 1, 0), upDir));
        const upQuat = Quaternion.fromAxisAngle(yAxis, yAngle);
        console.log('upQuat',upQuat)
        // 合并旋转
        upQuat.multiply(forwardQuat).normalize();
        this.rotation = upQuat;
        return upQuat
    }
}